﻿//-------------------------------------------------------------------------------
// <copyright file="ObjectContextExtender.cs" company="bbv Software Services AG">
//   Copyright (c) 2009 bbv Software Services AG
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
// </copyright>
//------------------------------------------------------------------------------

namespace bbv.DomainDrivenDesign.Contexts
{
    using System;
    using System.Data.Metadata.Edm;
    using System.Data.Objects;
    using System.Globalization;
    using System.Linq;
    using System.Reflection;

    /// <summary>
    /// Helper class to extend missing functionality of the <see cref="ObjectContext"/>.
    /// </summary>
    internal static class ObjectContextExtender
    {
        /// <summary>
        /// Gets the name of the entity set.
        /// </summary>
        /// <typeparam name="T">The type of the entity to get the name for.</typeparam>
        /// <param name="context">The context.</param>
        /// <returns>A string containing the name of the entity set.</returns>
        /// <exception cref="NotSupportedException">Thrown, if there is no EntitySet supporting the type 'T'.</exception>
        internal static string GetEntitySetName<T>(this ObjectContext context) where T : class
        {
            var container = context.MetadataWorkspace.GetEntityContainer(context.DefaultContainerName, true, DataSpace.CSpace);
            var entitySet =
                container.BaseEntitySets.AsQueryable().Where(
                    ebs => typeof(T).IsAssignableFrom(typeof(T).Module.GetType(ebs.ElementType.FullName))).FirstOrDefault();

            if (entitySet == null)
            {
                throw new NotSupportedException(
                    string.Format(
                        CultureInfo.InvariantCulture,
                        "There is no EntitySet supporting the type {0}",
                        typeof(T)));
            }

            return entitySet.Name;
        }

        /// <summary>
        /// Clears the cache from the MetadataWorkspace.
        /// </summary>
        /// <param name="context">The context.</param>
        internal static void ClearCache(this ObjectContext context)
        {
            var workspace = context.GetType().BaseType.GetField("_workspace", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(context);
            workspace.GetType().GetMethod("ClearCache").Invoke(workspace, null);
        }
    }
}
